#! /usr/local/bin/python
#-*- coding: utf-8 -*-

"""Sauvegarde des parties.

Les parties sont sauvegardées au format XML.
"""

"""
Minesweeper 3K. Original implementation of the classic game of mines
for Python 3.
Copyright (C) 2010  Cedric Bonhomme

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.

Minesweeper 3K  Copyright (C) 2010  Cedric Bonhomme
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
"""

__author__ = "Jerome Hussenet, Cedric Bonhomme"
__date__ = "$Date: 2010/02/27 $"
__copyright__ = "Copyright (c) 2010 Jerome Hussenet, Copyright (c) 2010 Cedric Bonhomme"
__license__ = "GPL 3"

import itertools
import time
import hashlib

class Sauvegarde(object):
    """Sauvegarde des parties.

    Permet la sauvegarde et le chargement des parties au format XML.
    """
    def __init__(self):
        """Initialisation.
        """
        self.doc = None
        self.readXML()

    def readXML(self, fichier = './sauvegarde/sauvegarde.xml'):
        """Parse le fichier XML.
        """
        from xml.dom.minidom import parse, Document
        try:
            self.doc = parse(fichier)
        except:
            self.doc = Document()
            racine = self.doc.createElement("sauvegarde")
            self.doc.appendChild(racine)

    def sauvegarde(self, grilleEtat, grilleMine, code, mines= 15, \
                            lon = 10, large = 10, temps = 0, niveau = 'debutant'):
        """Sauvegarde une partie.

        Sauvegarde une partie avec sa date, son éventuel code,
        le nombre de mines, la longueur, la largeur, le temps écoulé,
        le niveau et les 2 listes représentant le jeu.
        """
        from xml.dom.minidom import Document
        date = time.strftime('%d-%m-%y  %H:%M:%S', time.localtime())
        noLigne = 0
        if code != "":
            hashMD5 = hashlib.md5()
            hashMD5.update(code)
            codeHache = hashMD5.hexdigest()
        else:
            codeHache = ""

        try:
            racine = self.doc.getElementsByTagName('sauvegarde').item(0)
        except:
            self.doc = Document()
            racine = self.doc.createElement("sauvegarde")
            self.doc.appendChild(racine)

        partie = self.doc.createElement("partie")
        partie.setAttribute("date", date)
        partie.setAttribute("code", codeHache)

        try:
            self.doc.getElementsByTagName("sauvegarde").item(0).appendChild(partie)
        except:
            pass

        parametres = self.doc.createElement("parametres")
        partie.appendChild(parametres)

        nbMines = self.doc.createElement("nbMines")
        parametres.appendChild(nbMines)
        text = self.doc.createTextNode(str(mines))
        nbMines.appendChild(text)

        longueur = self.doc.createElement("longueur")
        parametres.appendChild(longueur)
        text = self.doc.createTextNode(str(lon))
        longueur.appendChild(text)

        largeur = self.doc.createElement("largeur")
        parametres.appendChild(largeur)
        text = self.doc.createTextNode(str(large))
        largeur.appendChild(text)

        temp = self.doc.createElement("temps")
        parametres.appendChild(temp)
        text = self.doc.createTextNode(str(temps))
        temp.appendChild(text)

        nivo = self.doc.createElement("niveau")
        parametres.appendChild(nivo)
        text = self.doc.createTextNode(niveau)
        nivo.appendChild(text)

        for ligneEtat, ligneMine in zip(grilleEtat, grilleMine):
            noLigne = noLigne + 1
            try:
                noeud = self.doc.getElementsByName("ligne"+str(noLigne))
            except:
                noeud = self.doc.createElement("ligne"+str(noLigne))
                partie.appendChild(noeud)

            for caseEtat, caseMine in zip(ligneEtat, ligneMine):
                element = self.doc.createElement("case")
                noeud.appendChild(element)
                element.setAttribute("mine", caseMine)
                caseText = self.doc.createTextNode(str(caseEtat))
                element.appendChild(caseText)
        return self.doc

    def chargement(self, date = "", code = "", tout = False):
        """Charge une partie.

        Renvoie un tuple contenant la date, le temps, le niveau,
        le nombre de mines, la longueur, la largeur,
        la liste de liste des états et la liste de liste de liste indiquant
        la présence de mines de la partie correspondant à la date.

        Si _tout_ est à True la fonction renvoie tous les scores.
        """
        grilleEtat, grilleMine, resultat = [], [], []
        if code != "":
            hashMD5 = hashlib.md5()
            hashMD5.update(code)
            codeHache = hashMD5.hexdigest()
        else:
            codeHache = ""

        for partie in self.doc.getElementsByTagName("sauvegarde").item(0).childNodes:
            if (tout == True \
                or (partie.getAttribute("date") == date \
                and partie.getAttribute("code") == codeHache)):

                for data in partie.getElementsByTagName("parametres").item(0).childNodes:
                    nbMines = int(partie.getElementsByTagName("nbMines").item(0).childNodes.item(0).nodeValue)
                    longueur = int(partie.getElementsByTagName("longueur").item(0).childNodes.item(0).nodeValue)
                    largeur = int(partie.getElementsByTagName("largeur").item(0).childNodes.item(0).nodeValue)
                    temps = int(partie.getElementsByTagName("temps").item(0).childNodes.item(0).nodeValue)
                    niveau = partie.getElementsByTagName("niveau").item(0).childNodes.item(0).nodeValue

                for ligne in partie.childNodes:
                    ligneEtat, ligneMine = [], []
                    for case in ligne.getElementsByTagName("case"):
                        ligneEtat.append(int(case.childNodes.item(0).nodeValue))
                        ligneMine.append(case.getAttribute("mine"))
                    if ligneEtat != [] and ligneMine != []:
                        grilleEtat.append(ligneEtat)
                        grilleMine.append(ligneMine)
                resultat.append((partie.getAttribute("date"), temps, niveau, nbMines, longueur, largeur, grilleEtat, grilleMine))
        return resultat

    def estProtege(self, date):
        """Vérifie si une partie est protégée.

        Renvoie True si la partie est protégée par mot de passe, False sinon.
        """
        for partie in self.doc.getElementsByTagName("sauvegarde").item(0).childNodes:
            if (partie.getAttribute("date") == date \
                and partie.getAttribute("code") == ""):
                return False
            elif (partie.getAttribute("date") == date \
                and partie.getAttribute("code") != ""):
                return True

    def supprime(self, date = ""):
        """Supprime une partie.

        La partie est supprimée selon la date.
        Si deux parties de même date existent,
        seule la première est supprimée.
        """
        for partie in self.doc.getElementsByTagName("sauvegarde").item(0).childNodes:
            if partie.getAttribute("date") == date:
                while partie.childNodes:
                    partie.removeChild(partie.firstChild)
                partie.parentNode.removeChild(partie)
                break

    def write(self, fichier = './sauvegarde/sauvegarde.xml'):
        """Sauvegarde le fichier XML.
        """
        try:
            file = open(fichier, 'w')
            file.write("%s" % self.doc.toxml())
        except IOError as e:
            print(_("Erreur d'écriture :"), e)
        finally:
            file.close()

    def __str__(self):
        """Affichage élégant du fichier XML.
        """
        return self.doc.toprettyxml()

if __name__ == "__main__":
    # Point d'entrée en exécution.
    grilleEtat = [[0,1,2,0,1], [0,0,1,0,1], [2,1,0,0,1]]
    grilleMine = [['m','','','m',''], ['m','','','',''], ['','m','m','','']]
    grilleEtat1 = [[0,1,2,0,1], [0,0,1,0,1], [2,1,0,0,1]]
    grilleMine1 = [['','m','','',''], ['','m','m','',''], ['','','','','m']]
    sauv = Sauvegarde()
    sauv.sauvegarde(grilleEtat, grilleMine, mines= 15, lon = 10, large = 10, code = "lustucru", niveau = "debutant")
    sauv.sauvegarde(grilleEtat1, grilleMine1, mines= 25, lon = 12, large = 12, code = "pepito")
    #sauv.write()
    print("sauvegarde :\n")
    print(sauv)
    print("chargement :\n")
    date = time.strftime('%d-%m-%y  %H:%M:%S', time.localtime())
    print(sauv.chargement(tout = True))
    print("suppression:\n")
    date1 = time.strftime('%d-%m-%y  %H:%M', time.localtime())
    sauv.supprime(date1)
    #print sauv.chargement(date, "pepito")
    print(sauv.chargement(date, "lustucru"))